﻿using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SetUPN
{
    class Program
    {
        static void Main(string[] args)
        {
            string domain = "";
            string sAMAccountName = "";
            string email = "";
            string queryAD = "";

            Console.WriteLine("-------------------------------------------------------------------------------");
            Console.WriteLine("--                   Set UPN             (c) 2014 Dougie Birrell             --");
            Console.WriteLine("-------------------------------------------------------------------------------");
            Console.WriteLine("");
            Console.WriteLine("This program will set the 'userPrincipleName' attribute on AD objects to be the same as the 'mail' attribute on that object.");
            Console.WriteLine("This allows users to log into a windows computer using their email address instead of a login name.");
            Console.WriteLine("You must have a valid email address fred@foobar.org in the 'mail' attribute, you must also be wanting to use foobar.org as your UPN");
            Console.WriteLine("If you are not careful you can break Active Directory objects by running this, please be familiar with AD attributes");
            Console.WriteLine("");
            Console.WriteLine("WARNING: If you do not know what ADSI Edit is, or how to use it, or if you are unsure generally DO NOT RUN this program.");
            Console.WriteLine("");
            Console.WriteLine("DISCLAIMER: I accept no responsibility if you make a serious or silly mistake as a result of using this program, or by editing or by cannibalising parts of it. You are responsible for your actions.");
            Console.WriteLine("");
            Console.Write("If you're ready, please type in your domain name : ");
            domain = Console.ReadLine();
        
    
            // Tell the program what the domain we are querying is. 
            System.DirectoryServices.DirectoryEntry myDomain = new System.DirectoryServices.DirectoryEntry("LDAP://" + domain);
            System.DirectoryServices.DirectorySearcher mySearcher = new System.DirectoryServices.DirectorySearcher(myDomain);

            // This is the query we run. You can create different ones by running 'Active Directory Users and Computers' and entering a custom LDAP query.
            queryAD = "(&(objectClass=user)(objectClass=organizationalPerson)(objectCategory=person))";
            mySearcher.Filter = (queryAD);

            // For each entry returned try and get the 'sAMAAccountName' and 'mail' attribute.
            foreach (System.DirectoryServices.SearchResult resEnt in mySearcher.FindAll())
            {
                try
                {
                    System.DirectoryServices.DirectoryEntry de = resEnt.GetDirectoryEntry();

                    try
                    {
                        sAMAccountName = de.Properties["sAMAccountName"].Value.ToString();
                        // Check the account name doesn't begin IWAN_ or IUSR_ if it does, ignore it.
                        if ((sAMAccountName.Contains("IWAM_")) || (sAMAccountName.Contains("IUSR_")))
                        {
                            // Do nothing
                        }
                        else // get the 'mail' attribute and call the procedure to write it to the userPrincipalName
                        {
                            try
                            {
                                email = de.Properties["mail"].Value.ToString();
                                UpdateAD(sAMAccountName, email, domain);
                            }
                            catch
                            {
                                Console.WriteLine(sAMAccountName + " has no value entered in the 'mail' field.");
                            }
                        }
                    }
                    catch (Exception e1)
                    {
                        Console.WriteLine("Problem querying Active Directory :-( \n\n" + e1);
                    }
                }
                catch (Exception e2)
                {
                    Console.WriteLine("Problem querying Active Directory :-( \n\n" + e2);
                }
            }
        }

        static void UpdateAD(string sAMAccountName, string email, string domain)
        {
            string searchfilter = "(sAMAccountName=" + sAMAccountName + ")";
            DirectoryEntry d = null;

            try
            {
                System.DirectoryServices.DirectoryEntry myDomain = new System.DirectoryServices.DirectoryEntry("LDAP://" + domain);
                System.DirectoryServices.DirectorySearcher mySearcher = new System.DirectoryServices.DirectorySearcher(myDomain);

                mySearcher.Filter = (searchfilter);
                System.DirectoryServices.SearchResult resEnt = mySearcher.FindOne();
                d = new DirectoryEntry();
                d.Path = resEnt.Path;

                d.Properties["userPrincipalName"].Value = email;
                d.CommitChanges();
            }
            // ADUe = ActiveDirectoryUsersException
            catch (Exception ADUe)
            {
                Console.WriteLine("Active Directory Write Error :-( \n\n" + ADUe);
            }
        }
    }
}
